package cn.xchats.rpc.server;

import cn.xchats.rpc.common.type.ZookeeperNodeType;
import io.netty.channel.ChannelInitializer;
import cn.xchats.rpc.common.core.ZookeeperService;
import cn.xchats.rpc.common.util.PropertyUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;

/*
 *
 *@author teddy
 *@date 2018/6/26
 */
@Service
@Order(1)
public class TcpServer implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        try {
            port = Integer.valueOf(PropertyUtil.getProperty("tcp.server.port"));
        } catch (NumberFormatException e) {
        }
        run();
    }

    private static int port;

    private static final int portDefault = 8888;

    public TcpServer() {
        this.port = portDefault;
    }

    public TcpServer(int port) {
        this.port = port;
    }

    public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    /*.childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            // readerIdleTime：为读超时时间（即测试端一定时间内未接受到被测试端消息）
                            //writerIdleTime：为写超时时间（即测试端一定时间内向被测试端发送消息）
                            //allIdleTime：所有类型的超时时间
                            //单位
                            ch.pipeline().addLast(new IdleStateHandler(10, 10, 20, TimeUnit.SECONDS));
                            ch.pipeline().addLast(new TcpServerHander());
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());
                        }
                    })*/
                    .childHandler(new ServerObjectCodecHandler())
                    .option(ChannelOption.SO_BACKLOG, 1024) //设置tcp缓冲区
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture f = bootstrap.bind(port).sync();

            //开始 注册服务
            //registerService();
            System.out.println("TcpServer 已启动...");
            //f.channel().closeFuture().sync();
        } finally {
           //workerGroup.shutdownGracefully();
            //bossGroup.shutdownGracefully();
        }
    }

    /**
     * 服务注册
     */
/*
    public void registerService() {
        String hostAddress = null;
        try {
            hostAddress = InetAddress.getLocalHost().getHostAddress();
            ZookeeperNodeType.hostAddress=hostAddress;
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        //主节点是否存在
        if (!zookeeperService.checkNodePath(ZookeeperNodeType.SERVER_TYPE))
            zookeeperService.createEmptyNode(ZookeeperNodeType.SERVER_TYPE);

        //临时存在说明 client端宕机之后 zookeeper的服务端心跳还没来得及开始检测 所以节点没删除（可以在zookeeper里设置心跳间隔  或者在这判断一下）
        if (zookeeperService.checkNodePath(ZookeeperNodeType.SERVER_TYPE + "/" + hostAddress))
            zookeeperService.deleteNode(ZookeeperNodeType.SERVER_TYPE + "/" + hostAddress);
        zookeeperService.createEphemeralEmptyNode(ZookeeperNodeType.SERVER_TYPE + "/" + hostAddress);

        System.out.println("服务已完成注册");
    }
*/

}
